package com.test.context;

import com.test.environment.ConfigurableEnvironment;
import com.test.factory.DefaultListableBeanFactory;
import com.test.reader.XmlBeanDefinitionReader;
import com.test.resource.Resource;

/**
 * AbstractXmlApplicationContext类是一个抽象的XML应用上下文，
 * 继承自AbstractRefreshableApplicationContext，主要用于从XML配置中加载bean定义。
 */
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext{

    /**
     * 加载bean定义的方法，通过XmlBeanDefinitionReader读取配置信息。
     * 首先尝试从getConfigResources方法获取资源配置，如果为空，则尝试从getConfigLocations获取配置位置。
     *
     * @param beanFactory DefaultListableBeanFactory类型的bean工厂，用于注册bean定义。
     * @throws Exception 如果加载过程中发生错误。
     */
    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws Exception {
        // 创建XmlBeanDefinitionReader实例，用于解析XML配置文件。
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // 获取XML配置资源
        Resource[] configResources = getConfigResources();
        // 如果配置资源不为空，加载这些资源中的bean定义
        if (configResources != null){
            xmlBeanDefinitionReader.loadBeanDefinitions(configResources);
        }

        // 获取XML配置位置
        String[] configLocations = getConfigLocations();
        // 如果配置位置不为空，加载这些位置中的bean定义
        if (configLocations != null){
            xmlBeanDefinitionReader.loadBeanDefinitions(configLocations);
        }
    }

    /**
     * 获取配置资源的方法，默认实现返回null。
     * 子类可以覆盖此方法以提供具体的配置资源。
     *
     * @return Resource[] 配置资源数组，如果没有配置资源则返回null。
     */
    protected Resource[] getConfigResources() {
        return null;
    }

    /**
     * 获取配置位置的抽象方法。
     * 子类必须实现此方法以提供具体的配置位置。
     *
     * @return String[] 配置位置数组。
     */
    protected abstract String[] getConfigLocations();

    /**
     * 设置环境配置的方法，本实现为空。
     * 子类可以覆盖此方法以提供具体的环境配置逻辑。
     *
     * @param environment ConfigurableEnvironment类型的环境配置。
     */
    @Override
    public void setEnvironment(ConfigurableEnvironment environment) {
        // 本实现为空，子类可以覆盖此方法
    }

    /**
     * 获取应用名称的方法，返回一个空字符串。
     * 子类可以覆盖此方法以提供具体的应用名称。
     *
     * @return String 应用名称，本实现返回空字符串。
     */
    @Override
    public String getApplicationName() {
        return "";
    }

    public boolean containsBeanDefinition(String beanName) {
        return getBeanFactory().containsBeanDefinition(beanName);
    }
}
